/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.ufes.gpf.sgm.dao;

import edu.ufes.gpf.sgm.model.Endereco;
import edu.ufes.gpf.sgm.model.Mandado;
import edu.ufes.gpf.sgm.model.Pessoa;
import edu.ufes.gpf.sgm.model.TipoMandado;
import edu.ufes.gpf.sgm.observer.Observador;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

/**
 *
 * @author Guilherme / Odair
 */
public class MandadosDAOMySQL extends AbstractDAOMySQL<Mandado> {

    private static MandadosDAOMySQL instancia;
    private List<Observador> observadores;

    private MandadosDAOMySQL() throws ClassNotFoundException, SQLException {
        conectar();
        observadores = new ArrayList<Observador>();
    }

    public static MandadosDAOMySQL getInstancia() throws ClassNotFoundException, SQLException {
        if (instancia == null) {
            instancia = new MandadosDAOMySQL();
        }
        return instancia;
    }

    @Override
    public boolean salvar(Mandado pObjeto) {
        try {
            consultar("INSERT INTO Mandado (numeroPessoal, numeroCentral, numeroAuto, dataDistribuicao, dataRecebimento, tipoMandado) VALUE ("
                    + pObjeto.getNumPessoal()
                    + ", "
                    + pObjeto.getNumCentral()
                    + ", "
                    + pObjeto.getNumAutos()
                    + ", '"
                    + pObjeto.getDataDistribuicao()
                    + "', '"
                    + pObjeto.getDataRecebimento()
                    + "', "
                    + pObjeto.getTipoMandado().getId()
                    + ")");
            for (Iterator<Pessoa> it = pObjeto.getPessoas().iterator(); it.hasNext();) {
                Pessoa pessoa = it.next();
                consultar("INSERT INTO MandadoPessoa (mandado, pessoa) VALUE ("
                        + pObjeto.getId()
                        + ", "
                        + pessoa.getId()
                        + ")");
            }
            notificarObserver();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean atualizar(Mandado pObjeto) {
        try {
            consultar("UPDATE Mandado SET "
                    + "numeroPessoal = " + pObjeto.getNumPessoal()
                    + ", numeroCentral = " + pObjeto.getNumCentral()
                    + ", numeroAuto = " + pObjeto.getNumAutos()
                    + "', dataRecebimento = '" + pObjeto.getDataRecebimento()
                    + "', dataDistribuicao = '" + pObjeto.getDataDistribuicao()
                    + ", tipoMandado = " + pObjeto.getTipoMandado().getId()
                    + "' WHERE objectIdentifier = " + pObjeto.getId());

            consultar("DELETE FROM MandadoPessoa WHERE (mandado = '" + pObjeto.getId() + ")");

            for (Iterator<Pessoa> it = pObjeto.getPessoas().iterator(); it.hasNext();) {
                Pessoa pessoa = it.next();
                consultar("INSERT INTO MandadoPessoa (mandado, pessoa) VALUE ("
                        + pObjeto.getId()
                        + ", "
                        + pessoa.getId()
                        + ")");
            }

            notificarObserver();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean remover(Mandado pObjeto) {
        try {
            consultar("DELETE FROM Mandado WHERE (numeroPessoal = '" + pObjeto.getNumPessoal()
                    + "' AND objectIdentifier = "
                    + pObjeto.getId()
                    + ")");
            notificarObserver();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public Mandado buscarPorId(int pObjetoId) {
        try {
            ResultSet rs = consultar("SELECT m.objectIdentifier, m.numeroPessoal, m.numeroCentral, m.numeroAuto, m.dataDistribuicao, m.dataRecebimento"
                    + ", tm.objectIdentifier, tm.nome, tm.descricao "
                    + "FROM Mandado m INNER JOIN TipoMandado tm "
                    + "ON tm.objectIdentifier = m.tipoMandado "
                    + "WHERE m.objectIdentifier = " + pObjetoId);
            rs.next();
            Mandado retorno;
            if (rs.getRow() == 0) {
                retorno = null;
            } else {
                TipoMandado tp = new TipoMandado(rs.getString("tm.nome"), rs.getString("tm.descricao"));
                tp.setId(rs.getInt("tm.objectIdentifier"));
                retorno = new Mandado(rs.getInt("m.numeroPessoal"), rs.getInt("m.numeroPessoal"), rs.getInt("m.numeroPessoal"), rs.getString("m.dataDistribuicao"), rs.getString("m.dataRecebimento"), tp);
                retorno.setId(rs.getInt("m.objectIdentifier"));
                
                ResultSet rs2 = consultar("SELECT p.nomeCompleto, p.apelido, p.CPF, p.endereco, e.objectIdentifier, e.logradouro, e.cidade, e.UF "
                        + "FROM Mandado m INNER JOIN MandadoPessoa mp "
                        + "ON m.objectIdentifier = mp.mandado "
                        + "INNER JOIN Pessoa p "
                        + "ON p.objectIdentifier = mp.pessoa "
                        + "INNER JOIN Endereco e "
                        + "ON e.objectIdentifier = p.endereco "
                        + "WHERE m.objectIdentifier = " + retorno.getId());
                
                while (rs2.next()) {
                    Endereco e = new Endereco(rs2.getString("e.cidade"), rs2.getString("e.UF"), rs2.getString("e.logradouro"));
                    e.setId(rs2.getInt("e.objectIdentifier"));
                    Pessoa p = new Pessoa(rs2.getString("p.nomeCompleto"), rs2.getString("p.CPF"), rs2.getString("p.telefone"), rs2.getString("p.apelido"), e);
                    p.setId(rs.getInt("p.objectIdentifier"));
                    
                    retorno.addPessoas(p);
                }
            }
            return retorno;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

   public Collection<Mandado> buscarPorNumeroAuto(int pObjetoNumeroAutos) {
        try {
            ResultSet rs = consultar("SELECT m.objectIdentifier, m.numeroPessoal, m.numeroCentral, m.numeroAuto, m.dataDistribuicao, m.dataRecebimento"
                    + ", tm.objectIdentifier, tm.nome, tm.descricao "
                    + "FROM Mandado m INNER JOIN TipoMandado tm "
                    + "ON tm.objectIdentifier = m.tipoMandado"
                    + "WHERE m.numeroAuto = "+pObjetoNumeroAutos);
            
            Collection<Mandado> retorno = new TreeSet<Mandado>();
            while (rs.next()) {
                TipoMandado tp = new TipoMandado(rs.getString("tm.nome"), rs.getString("tm.descricao"));
                tp.setId(rs.getInt("tm.objectIdentifier"));
                Mandado m = new Mandado(rs.getInt("m.numeroPessoal"), rs.getInt("m.numeroPessoal"), rs.getInt("m.numeroPessoal"), rs.getString("m.dataDistribuicao"), rs.getString("m.dataRecebimento"), tp);
                m.setId(rs.getInt("m.objectIdentifier"));

                ResultSet rs2 = consultar("SELECT p.nomeCompleto, p.apelido, p.CPF, p.endereco, e.objectIdentifier, e.logradouro, e.cidade, e.UF "
                        + "FROM Mandado m INNER JOIN MandadoPessoa mp "
                        + "ON m.objectIdentifier = mp.mandado "
                        + "INNER JOIN Pessoa p "
                        + "ON p.objectIdentifier = mp.pessoa "
                        + "INNER JOIN Endereco e "
                        + "ON e.objectIdentifier = p.endereco "
                        + "WHERE m.objectIdentifier = " + m.getId());

                while (rs2.next()) {
                    Endereco e = new Endereco(rs2.getString("e.cidade"), rs2.getString("e.UF"), rs2.getString("e.logradouro"));
                    e.setId(rs2.getInt("e.objectIdentifier"));
                    Pessoa p = new Pessoa(rs2.getString("p.nomeCompleto"), rs2.getString("p.CPF"), rs2.getString("p.telefone"), rs2.getString("p.apelido"), e);
                    p.setId(rs.getInt("p.objectIdentifier"));
                    
                    m.addPessoas(p);
                }

                retorno.add(m);
            }
            return retorno;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    @Override
    public int ultimoObjectIdentifier() {
        try {
            ResultSet rs = consultar("SELECT MAX(objectIdentifier) FROM Mandado");
            rs.next();
            int retorno;
            if (rs.getRow() == 0) {
                retorno = 0;
            } else {
                retorno = rs.getInt("MAX(objectIdentifier)");
            }
            return retorno;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    @Override
    public Collection<Mandado> buscarTodos() {
        try {
            ResultSet rs = consultar("SELECT m.objectIdentifier, m.numeroPessoal, m.numeroCentral, m.numeroAuto, m.dataDistribuicao, m.dataRecebimento"
                    + ", tm.objectIdentifier, tm.nome, tm.descricao "
                    + "FROM Mandado m INNER JOIN TipoMandado tm "
                    + "ON tm.objectIdentifier = m.tipoMandado");
            Collection<Mandado> retorno = new TreeSet<Mandado>();
            while (rs.next()) {
                TipoMandado tp = new TipoMandado(rs.getString("tm.nome"), rs.getString("tm.descricao"));
                tp.setId(rs.getInt("tm.objectIdentifier"));
                Mandado m = new Mandado(rs.getInt("m.numeroPessoal"), rs.getInt("m.numeroPessoal"), rs.getInt("m.numeroPessoal"), rs.getString("m.dataDistribuicao"), rs.getString("m.dataRecebimento"), tp);
                m.setId(rs.getInt("m.objectIdentifier"));

                ResultSet rs2 = consultar("SELECT p.nomeCompleto, p.apelido, p.CPF, p.endereco, e.objectIdentifier, e.logradouro, e.cidade, e.UF "
                        + "FROM Mandado m INNER JOIN MandadoPessoa mp "
                        + "ON m.objectIdentifier = mp.mandado "
                        + "INNER JOIN Pessoa p "
                        + "ON p.objectIdentifier = mp.pessoa "
                        + "INNER JOIN Endereco e "
                        + "ON e.objectIdentifier = p.endereco "
                        + "WHERE m.objectIdentifier = " + m.getId());

                while (rs2.next()) {
                    Endereco e = new Endereco(rs2.getString("e.cidade"), rs2.getString("e.UF"), rs2.getString("e.logradouro"));
                    e.setId(rs2.getInt("e.objectIdentifier"));
                    Pessoa p = new Pessoa(rs2.getString("p.nomeCompleto"), rs2.getString("p.CPF"), rs2.getString("p.telefone"), rs2.getString("p.apelido"), e);
                    p.setId(rs.getInt("p.objectIdentifier"));
                    
                    m.addPessoas(p);
                }

                retorno.add(m);
            }
            return retorno;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void addObserver(Observador o) {
        observadores.add(o);
    }

    @Override
    public void removerObserver(Observador o) {
        observadores.remove(o);
    }

    @Override
    public void notificarObserver() {
        for (Iterator<Observador> it = observadores.iterator(); it.hasNext();) {
            Observador observador = it.next();
            observador.atualizar();
        }
    }
}
